import cn from 'classnames';
import React, { useState, useEffect, useMemo } from 'react';
import PropTypes from 'prop-types';
import { Link } from 'react-router-dom';
import { Line } from 'rc-progress';
import Upload from 'rc-upload';
import fetch from 'API/fetch';
import FormData from 'form-data';
import { withRouter } from 'react-router';
import {
	CheckmarkOutline32 as Success9,
	Help16 as Icon,
	ChevronRight32,
	ChevronLeft32,
} from '@carbon/icons-react';
import Tooltip from '@kuiper-components/tooltip';
import notification from '@kuiper-components/notification';
import Tabs, { TabPane } from '@kuiper-components/tabs';
import Input from '@kuiper-components/input';
import Button from '@kuiper-components/button';

import HostSearchInput from '../../components/HostSearchInput';
import Breadcrumb, { Item } from '../../components/Breadcrumb';
import s from './style.module.css';
import HostAdd from './HostAdd';
const Step2Html = ({ text, percent }) => {
	return (
		<div>
			<p className={cn(s.tac, s.percent)}>{percent}%</p>
			<Line percent={percent} strokeWidth="2" strokeColor="#0b6df6" />
			<p className={s.tac}>资产正在{text}，请稍等...</p>
		</div>
	);
};
Step2Html.propTypes = {
	text: PropTypes.string.isRequired,
	percent: PropTypes.number,
};

const tooltipInfo = (
	<div>
		<p>1.按子域名获取，支持导入A记录、CNAME记录及AAAA记录;</p>
		<p>2.主机名为“@”，默认导入主域名;</p>
		<p>3.已上传SSL证书的资产默认协议“https”，否则为“http”;</p>
		<p>4.过滤已导入ScanV的云防御资产。</p>
	</div>
);

const Step3Html = ({ total, success, error, data }) => {
	return (
		<div>
			<p>
				<span>总计：{total}</span>
				<span className={s.ml20}>成功：{success}</span>
				<span className={s.ml20}>失败：{error}</span>
			</p>
			{error > 0 && (
				<>
					<p className={s.tit}>添加失败资产如下：</p>
					<div>
						<div className={s.tabletit}>
							<span>资产名称</span>
							<span>资产地址</span>
							<span>源站IP</span>
							<span>失败原因</span>
						</div>
						<ul className={s.errortable}>
							{data.length &&
								data.map((item, index) => (
									<li key={index}>
										<span
											style={{
												maxWidth: 'calc(100% / 4)',
												overflow: 'hidden',
												textOverflow: 'ellipsis',
											}}
											title={item.name}
										>
											{item.name}
										</span>
										<span
											style={{
												maxWidth: 'calc(100% / 4)',
												overflow: 'hidden',
												textOverflow: 'ellipsis',
											}}
											title={item.address}
										>
											{item.address}
										</span>
										<span
											style={{
												maxWidth: 'calc(100% / 4)',
												overflow: 'hidden',
												textOverflow: 'ellipsis',
											}}
											title={item.sourceIp}
										>
											{item.sourceIp || '- -'}
										</span>
										<span
											style={{
												maxWidth: 'calc(100% / 4)',
												overflow: 'hidden',
												textOverflow: 'ellipsis',
											}}
											title={item.source}
										>
											{item.source}
										</span>
									</li>
								))}
						</ul>
					</div>
				</>
			)}
			{error === 0 && (
				<div className={s.icons}>
					<Success9 className={s.success} />
					<p>全部添加成功</p>
				</div>
			)}
		</div>
	);
};
Step3Html.propTypes = {
	total: PropTypes.number,
	success: PropTypes.number,
	error: PropTypes.number,
	data: PropTypes.array,
};

const NotData = () => {
	return (
		<div className={cn(s.tac, s.nodata)}>
			<svg
				className={s.img}
				width="184"
				height="152"
				viewBox="0 0 184 152"
				xmlns="http://www.w3.org/2000/svg"
			>
				<g fill="none" fillRule="evenodd">
					<g transform="translate(24 31.67)">
						<ellipse
							className={s.imgDefaultEllipse}
							cx="67.797"
							cy="106.89"
							rx="67.797"
							ry="12.668"
						></ellipse>
						<path
							className={s.imgDefaultPath1}
							d="M122.034 69.674L98.109 40.229c-1.148-1.386-2.826-2.225-4.593-2.225h-51.44c-1.766 0-3.444.839-4.592 2.225L13.56 69.674v15.383h108.475V69.674z"
						></path>
						<path
							className={s.imgDefaultPath2}
							d="M101.537 86.214L80.63 61.102c-1.001-1.207-2.507-1.867-4.048-1.867H31.724c-1.54 0-3.047.66-4.048 1.867L6.769 86.214v13.792h94.768V86.214z"
							transform="translate(13.56)"
						></path>
						<path
							className={s.imgDefaultPath3}
							d="M33.83 0h67.933a4 4 0 0 1 4 4v93.344a4 4 0 0 1-4 4H33.83a4 4 0 0 1-4-4V4a4 4 0 0 1 4-4z"
						></path>
						<path
							className={s.imgDefaultPath4}
							d="M42.678 9.953h50.237a2 2 0 0 1 2 2V36.91a2 2 0 0 1-2 2H42.678a2 2 0 0 1-2-2V11.953a2 2 0 0 1 2-2zM42.94 49.767h49.713a2.262 2.262 0 1 1 0 4.524H42.94a2.262 2.262 0 0 1 0-4.524zM42.94 61.53h49.713a2.262 2.262 0 1 1 0 4.525H42.94a2.262 2.262 0 0 1 0-4.525zM121.813 105.032c-.775 3.071-3.497 5.36-6.735 5.36H20.515c-3.238 0-5.96-2.29-6.734-5.36a7.309 7.309 0 0 1-.222-1.79V69.675h26.318c2.907 0 5.25 2.448 5.25 5.42v.04c0 2.971 2.37 5.37 5.277 5.37h34.785c2.907 0 5.277-2.421 5.277-5.393V75.1c0-2.972 2.343-5.426 5.25-5.426h26.318v33.569c0 .617-.077 1.216-.221 1.789z"
						></path>
					</g>
					<path
						className={s.imgDefaultPath5}
						d="M149.121 33.292l-6.83 2.65a1 1 0 0 1-1.317-1.23l1.937-6.207c-2.589-2.944-4.109-6.534-4.109-10.408C138.802 8.102 148.92 0 161.402 0 173.881 0 184 8.102 184 18.097c0 9.995-10.118 18.097-22.599 18.097-4.528 0-8.744-1.066-12.28-2.902z"
					></path>
					<g className={s.imgDefaultG} transform="translate(149.65 15.383)">
						<ellipse cx="20.654" cy="3.167" rx="2.849" ry="2.815"></ellipse>
						<path d="M5.698 5.63H0L2.898.704zM9.259.704h4.985V5.63H9.259z"></path>
					</g>
				</g>
			</svg>
			<p className={s.tac}>暂无数据</p>
		</div>
	);
};

function Batch({
	match: {
		params: { assetType },
	},
}) {
	const [step, setStep] = useState(1);
	let [leftData, setLeftData] = useState([]);
	let [rightData, setRightData] = useState([]);
	let [leftValue, setLeftValue] = useState(false);
	let [rightValue, setRightValue] = useState(false);
	const [enable, setEnable] = useState(true);
	const [enabler, setEnabler] = useState(true);
	const [progress, setProgress] = useState(0);
	const [activeKey, setActiveKey] = useState('local');
	const [dataNum, setDataNum] = useState({ total: 0, success: 0, error: -1 });
	const [tdata, setTdata] = useState([]);
	const [initLeft, setInitLeft] = useState([]);
	const [initRight, setInitRight] = useState([]);
	// 封装整体步骤的方法
	function getStatus() {
		fetch('/api/v2/jobs/batch_status?asset_type=web', {
			method: 'GET',
		}).then(res => {
			if (!res.type) {
				setActiveKey(x => (x = 'local'));
				changeTab(1);
			} else {
				setActiveKey(x => (x = res.type));
				if (res.progress === 100) {
					const len = res.assets.length;
					let successLen = 0;
					const data = [];
					res.assets.forEach(item => {
						if (item.status === '成功') {
							successLen += 1;
						} else {
							data.push({
								name: item.name,
								address: item.target,
								sourceIp: item.sourceIp,
								source: item.detail,
							});
						}
					});
					setDataNum(x => ({
						total: len,
						success: successLen,
						error: len - successLen,
					}));
					setTdata(x => (x = data));
					changeTab(3);
				} else {
					changeTab(2);
					let timer = '';
					timer = setInterval(() => {
						fetch('/api/v2/jobs/batch_status?asset_type=web', {
							method: 'GET',
						}).then(res => {
							if (res.progress === 100) {
								clearInterval(timer);
								getStatus();
								changeTab(3);
							} else {
								setProgress(x => (x = res.progress));
							}
						});
					}, 2000);
				}
			}
		});
	}
	// 获取数据
	useEffect(() => {
		getStatus();
	}, [assetType]);
	const customReq = obj => {
		const formData = new FormData();
		formData.append('file', obj.file);
		fetch('/api/v2/jobs/batch_import', {
			method: 'POST',
			body: formData,
		})
			.then(res => {
				if (res.code === 200) {
					getStatus();
				}
			})
			.catch(e => {
				notification.error({
					message: e.message,
					placement: 'top',
				});
				setTimeout(() => {
					changeTab(1);
				}, 5000);
			});
	};
	// 统一云防御导入资产
	const [isImport, setIsImport] = useState(false);
	const UcdpImport = () => {
		if (isImport) return false;
		setIsImport(true);
		const data = JSON.stringify(rightData);
		fetch('/api/v2/jobs/batch_import', {
			method: 'POST',
			body: data,
			checkStatus: 501,
		})
			.then(res => {
				if (res.code === 200) {
					getStatus();
					setIsImport(false);
				} else {
					notification.error({
						message: res.msg || '上传错误',
						placement: 'top',
					});
					setIsImport(false);
				}
			})
			.catch(err => {
				setIsImport(false);
			});
	};
	// 获取云防御资产
	const getAsset = () => {
		return fetch('/api/v2/jobs/cloud_assets', {
			method: 'GET',
		}).then(res => {
			if (res.code === 200) {
				if (res.imported_count === 0 && !res.assets.length) {
					notification.error({
						message: '该用户暂无可导入ScanV的云防御资产',
						placement: 'top',
					});
					return;
				} else if (res.imported_count !== 0 && !res.assets.length) {
					notification.error({
						message: '该用户所有可导入ScanV的云防御资产已全部接入',
						placement: 'top',
					});
					return;
				}
				const arr = [];
				res.assets.forEach(item => {
					item.checked = false;
					arr.push(item);
				});
				setInitLeft(x => (x = arr));
				setLeftData(x => (x = arr));
				setRightData(x => (x = []));
			} else {
				notification.error({
					message: res.msg,
					placement: 'top',
				});
			}
		});
	};
	// 三栏切换
	function changeTab(n) {
		setStep(n);
	}
	// tab切换
	const handleTabChange = id => {
		setActiveKey(x => (x = id));
		changeTab(1);
	};
	// 继续添加
	const add = () => {
		changeTab(1);
		setLeftData(x => (x = []));
		setRightData(x => (x = []));
		setProgress(x => (x = 0));
		setDataNum(x => ({
			total: 0,
			success: 0,
			error: -1,
		}));
		fetch('/api/v2/jobs/batch_status?clean=1&asset_type=web', {
			method: 'get',
		}).then(res => {});
	};
	// 搜索
	const targetSearch = (val, type) => {
		val = val === undefined ? val : val.trim();
		if (val && type === 'left') {
			const arr = [];
			initLeft.forEach(item => {
				if (item.name.includes(val)) {
					arr.push(item);
				} else {
					if (item.target.includes(val)) {
						arr.push(item);
					}
				}
			});
			setLeftData((leftData = arr));
		} else if (val && type === 'right') {
			const arr = [];
			initRight.forEach(item => {
				if (item.name.includes(val)) {
					arr.push(item);
				} else {
					if (item.target.includes(val)) {
						arr.push(item);
					}
				}
			});
			setRightData((rightData = arr));
		} else if (!val && type === 'left') {
			setLeftData(x => (x = initLeft));
		} else if (!val && type === 'right') {
			setRightData(x => (x = initRight));
		}
	};
	// 文件大小校验
	const beforeUpload = f => {
		return new Promise((resolve, reject) => {
			if (f.size > 2 * 1024 * 1024) {
				notification.error({
					message: '文件大小超出限制',
					placement: 'top',
				});
				reject(new Error('文件大小超出限制'));
			}
			resolve(f);
		});
	};
	// 左全选
	const leftChange = val => {
		setLeftValue((leftValue = val));
		const arr = [];
		leftData.forEach(item => {
			item.checked = val;
			arr.push(item);
		});
		setLeftData((leftData = arr));
		if (leftData.length) setEnable(x => (x = !val));
	};
	// 右全选
	const rightChange = val => {
		setRightValue((rightValue = val));
		const arr = [];
		rightData.forEach(item => {
			item.checked = val;
			arr.push(item);
		});
		setRightData((rightData = arr));
		if (rightData.length) setEnabler(x => (x = !val));
	};
	// 判断是否有选中的数据
	function isCheck(data, type) {
		if (type === 'some') {
			return data.some(item => item.checked === true);
		}
		if (type === 'every') {
			return data.every(item => item.checked === true);
		}
	}
	const lens = useMemo(() => {
		const leftLen = leftData.filter(item => item.checked === true).length;
		const rightLen = rightData.filter(item => item.checked === true).length;
		return { leftLen, rightLen };
	}, [leftData, rightData]);
	// 每一个item选择
	const itemChange = (val, param, isLeft = true) => {
		if (isLeft) {
			const arr1 = [...leftData];
			arr1[param].checked = val;
			setLeftData((leftData = arr1));
			isCheck(leftData, 'some')
				? setEnable(x => (x = false))
				: setEnable(x => (x = true));
			isCheck(leftData, 'every')
				? setLeftValue(x => (x = true))
				: setLeftValue(x => (x = false));
		} else {
			const arr2 = [...rightData];
			arr2[param].checked = val;
			setRightData((rightData = arr2));
			isCheck(rightData, 'some')
				? setEnabler(x => (x = false))
				: setEnabler(x => (x = true));
			isCheck(rightData, 'every')
				? setRightValue(x => (x = true))
				: setRightValue(x => (x = false));
		}
	};
	// 添加
	const addItem = () => {
		const itemArr = [];
		const copyData = [...leftData];
		leftData.forEach(item => {
			if (item.checked) {
				item.checked = false;
				itemArr.push(item);
				const id = copyData.findIndex(item1 => item1.target === item.target);
				if (id > -1) copyData.splice(id, 1);
			}
		});
		const newArr = rightData.concat(itemArr);
		setLeftData((leftData = copyData));
		setInitLeft(x => (x = copyData));
		setRightData((rightData = newArr));
		setInitRight(x => (x = newArr));
		setLeftValue(x => (x = false));
		setEnable(x => (x = true));
	};
	// 移除
	const removeItem = () => {
		const itemArr1 = [...rightData];
		const itemArr2 = [...leftData];
		rightData.forEach(item => {
			if (item.checked) {
				item.checked = false;
				itemArr2.push(item);
				const id = itemArr1.findIndex(item1 => item1.target === item.target);
				if (id > -1) itemArr1.splice(id, 1);
			}
		});
		setRightData((rightData = itemArr1));
		setInitRight(x => (x = itemArr1));
		setLeftData((leftData = itemArr2));
		setInitLeft(x => (x = itemArr2));
		setRightValue(x => (x = false));
		setEnabler(x => (x = true));
	};
	return (
		<>
			<Breadcrumb className={s.bread}>
				<Item key="asset-manage" disabled>
					资产管理
				</Item>
				<Item key="manage/web">Web资产列表</Item>
				<Item>批量添加</Item>
			</Breadcrumb>
			<div
				className={cn(
					s.content,
					activeKey === 'local' && step === 1 ? s.con : ''
				)}
			>
				<Tabs
					onChange={handleTabChange}
					activeKey={activeKey}
					className={s.tabs}
				>
					<TabPane tab="本地添加" key="local">
						<div className={s.allstep}>
							<div className={cn(s.step, step !== 1 ? s.grey : false)}>
								{step !== 1 && <Success9 className={cn(s.iconsize, s.vam)} />}
								选择文件
								<span className={s.single}></span>
							</div>
							<div className={cn(s.step, s.ml10, step !== 2 ? s.grey : false)}>
								{step === 3 && <Success9 className={cn(s.iconsize, s.vam)} />}
								<span>批量添加</span>
								<span className={s.front}></span>
								<span className={s.single}></span>
							</div>
							<div className={cn(s.step, s.ml10, step !== 3 ? s.grey : false)}>
								添加结果
								<span className={s.front}></span>
							</div>
						</div>
						<div className={step === 1 ? s.info : step === 2 ? s.info : s.ins}>
							{step === 1 && (
								<div>
									<p>1.上传文件格式支持xls和xlsx，大小不超过2MB。</p>
									<p>2.每次最多可以添加500条记录。</p>
								</div>
							)}
							{step === 2 && <Step2Html text={'添加'} percent={progress} />}
							{step === 3 && (
								<Step3Html
									total={dataNum.total}
									success={dataNum.success}
									error={dataNum.error}
									data={tdata}
								/>
							)}
						</div>
						{step === 1 && (
							<div className={s.btns}>
								<Button
									className={s.def}
									onClick={() =>
										(window.location.href =
											'/api/v2/files/assets_template.xlsx')
									}
								>
									下载模版
								</Button>
								<Upload
									className={cn(s.ml20, s.upload)}
									accept={'.xlsx,.xls'}
									customRequest={customReq}
									beforeUpload={beforeUpload}
								>
									选择文件
								</Upload>
							</div>
						)}
						{step === 3 && (
							<div className={s.btns}>
								<Button className={s.def} onClick={add}>
									继续添加
								</Button>
								<Link to={'/asset-manage/manage/web'}>
									<Button primary className={s.ml20}>
										返回资产列表
									</Button>
								</Link>
							</div>
						)}
					</TabPane>
					<TabPane tab="云防御导入" key="cloud">
						<div className={s.allstep}>
							<div className={cn(s.step, step !== 1 ? s.grey : false)}>
								{step !== 1 && <Success9 className={cn(s.iconsize, s.vam)} />}
								选择资产
								<span className={s.single}></span>
							</div>
							<div className={cn(s.step, s.ml10, step !== 2 ? s.grey : false)}>
								{step === 3 && <Success9 className={cn(s.iconsize, s.vam)} />}
								<span>批量导入</span>
								<span className={s.front}></span>
								<span className={s.single}></span>
							</div>
							<div className={cn(s.step, s.ml10, step !== 3 ? s.grey : false)}>
								导入结果
								<span className={s.front}></span>
							</div>
						</div>
						<div className={step === 2 ? s.info : s.ins}>
							{step === 1 && (
								<div>
									<Button primary onClick={getAsset}>
										一键获取
									</Button>
									<div className={s.size}>
										<div className={s.left}>
											<div className={s.title}>
												<p style={{ marginBottom: 0 }}>
													<span className={cn(s.titinfo, s.vam)}>
														云防御资产
													</span>
													<Tooltip placement="top" overlay={tooltipInfo}>
														<Icon className={cn(s.ml10, s.vam)}></Icon>
													</Tooltip>
												</p>
												<span>
													{lens.leftLen}/{leftData.length}
												</span>
											</div>
											<div className={s.search}>
												<HostSearchInput
													placeholder="请输入搜索内容"
													onChange={e => targetSearch(e, 'left')}
													onpressEnter={targetSearch}
													className={s.items}
												></HostSearchInput>
												<div className={s.check}>
													<Input
														type="checkbox"
														className={s.mt2}
														onChange={leftChange}
														checked={leftValue}
													></Input>
													<span className={s.ml10}>全选</span>
												</div>
											</div>
											<ul className={s.allul}>
												{leftData.length ? (
													leftData.map((item, idx) => (
														<li className={s.li} key={idx}>
															<span className={s.names} title={item.name}>
																{item.name}
															</span>
															<span title={item.target} className={s.target}>
																{item.target}
															</span>
															<span
																title={item.sourceIp}
																className={s.sourceIp}
															>
																{item.sourceIp}
															</span>
															<Input
																type="checkbox"
																onChange={e => {
																	itemChange(e, idx);
																}}
																checked={item.checked}
															></Input>
														</li>
													))
												) : (
													<NotData />
												)}
											</ul>
										</div>
										<div className={cn(s.mid, s.tac)}>
											<div>
												<Button
													primary
													onClick={addItem}
													disabled={enable}
													className={s.midbtn}
												>
													添加
													<ChevronRight32 className={s.directicon} />
												</Button>
											</div>
											<div className={s.mt20}>
												<Button
													primary
													onClick={removeItem}
													disabled={enabler}
													className={cn(s.midbtn, s.remove)}
												>
													移除
													<ChevronLeft32
														className={cn(s.directicon, s.remove)}
													/>
												</Button>
											</div>
										</div>
										<div className={s.right}>
											<div className={s.title}>
												<span className={cn(s.titinfo, s.vam)}>导入ScanV</span>
												<span>
													{lens.rightLen}/{rightData.length}
												</span>
											</div>
											<div className={s.search}>
												<HostSearchInput
													onChange={e => targetSearch(e, 'right')}
													onpressEnter={targetSearch}
													placeholder="请输入搜索内容"
													className={s.items}
												></HostSearchInput>
												<div className={s.check}>
													<Input
														type="checkbox"
														className={s.mt2}
														onChange={rightChange}
														checked={rightValue}
													></Input>
													<span className={s.ml10}>全选</span>
												</div>
											</div>
											<ul className={s.allul}>
												{rightData.length ? (
													rightData.map((item, idx) => (
														<li className={s.li} key={idx}>
															<span className={s.names} title={item.name}>
																{item.name}
															</span>
															<span className={s.target} title={item.target}>
																{item.target}
															</span>
															<span
																title={item.sourceIp}
																className={s.sourceIp}
															>
																{item.sourceIp}
															</span>
															<Input
																type="checkbox"
																onChange={e => itemChange(e, idx, false)}
																checked={item.checked}
															></Input>
														</li>
													))
												) : (
													<NotData />
												)}
											</ul>
										</div>
									</div>
								</div>
							)}
							{step === 2 && <Step2Html text={'导入'} percent={progress} />}
							{step === 3 && (
								<Step3Html
									total={dataNum.total}
									success={dataNum.success}
									error={dataNum.error}
									data={tdata}
								/>
							)}
						</div>
						{step === 1 && (
							<div>
								{/* <p className={cn(s.warn, s.mt16)}>
									提示：从知道创宇云防御平台导入的域名资产无需授权认证，您可以直接使用ScanV
									默认参数配置，在资产列表开启监测任务及告警通知。
								</p> */}
								<div className={s.btns}>
									<Button primary disabled={isImport} onClick={UcdpImport}>
										批量导入
									</Button>
								</div>
							</div>
						)}
						{step === 3 && (
							<div className={s.btns}>
								<Button className={s.def} onClick={add}>
									继续导入
								</Button>
								<Link to={'/asset-manage/manage/web'}>
									<Button primary className={s.ml20}>
										返回资产列表
									</Button>
								</Link>
							</div>
						)}
					</TabPane>
				</Tabs>
			</div>
		</>
	);
}
Batch.propTypes = {
	className: PropTypes.string,
	history: PropTypes.shape({
		push: PropTypes.func.isRequired,
		replace: PropTypes.func.isRequired,
	}).isRequired,
	location: PropTypes.shape({
		search: PropTypes.string.isRequired,
	}).isRequired,
	match: PropTypes.shape({
		params: PropTypes.shape({
			assetType: PropTypes.string.isRequired,
		}).isRequired,
	}).isRequired,
};
export default withRouter(Batch);
